package com.object.module.lq.chatroom.websocketcomfig;


import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.object.module.lq.chatroom.service.NettyMsgService;
import com.object.utils.NettyChantTypeEnum;
import com.object.utils.NettyChantTypePojo;
import com.object.utils.NettyResponseData;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 聊天的ehandler
 * TextWebSocketFrame  用于为websockt处理文本的对象
 *
 * @author asus
 */
@Slf4j
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //用于记录和管理所有客户端的channel
    public static Map<Object, Channel> map = new ConcurrentHashMap<>();
    private Map<String, NettyMsgService> mapServiceMap;

    public ChatHandler(Map<String, NettyMsgService> map) {
        mapServiceMap = map;
    }


    public static Map<Object, Channel> getMap() {
        return map;
    }


    public static Map getUrlParams(String url) {
        Map<String, String> map = new HashMap<>();
        url = url.replace("?", ";");
        if (!url.contains(";")) {
            return map;
        }
        if (url.split(";").length > 0) {
            String[] arr = url.split(";")[1].split("&");
            for (String s : arr) {
                String key = s.split("=")[0];
                String value = s.split("=")[1];
                map.put(key, value);
            }
            return map;

        } else {
            return map;
        }
    }

//    /**
//     * 处理   ws连接上的参数
//     *
//     * @param ctx
//     * @param msg
//     * @throws Exception
//     */
//    @Override
//    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        //首次连接是FullHttpRequest，处理参数 by zhengkai.blog.csdn.net
//        //检查token合法
//        if (msg instanceof FullHttpRequest) {
//            try {
//                examineToken(ctx, msg);
//                NettyResponseData.ok().msg("连上成功").sendOk(ctx.channel());
//            } catch (Exception e) {
//                log.error(e.getMessage());
//                NettyResponseData.err().msg("请连接服务器时带上正确的token哦").sendErr(ctx.channel());
//            }
//           // ctx.pipeline().remove(ChatHandler.class);
//        }else{
//            channelRead0(ctx, (TextWebSocketFrame) msg);
//        }
//
//
//    }

    /**
     * 根据token获取id
     *
     * @param saToken
     * @return
     */
    private Integer byTokenGetId(String saToken) {
        return (Integer) StpUtil.getLoginIdByToken(saToken);
    }

    /**
     * //根据传入过来的token 获取对应的id
     *
     * @param ctx
     * @param msg
     */
    private Integer examineToken(ChannelHandlerContext ctx, Object msg) throws Exception {
        FullHttpRequest request = (FullHttpRequest) msg;
        String uri = request.uri();
        Map paramMap = getUrlParams(uri);
        Integer id = Integer.valueOf(String.valueOf(paramMap.get("id")));
        map.put(id, ctx.channel());
        log.info("连接上来一个客户端：{}", id);
        return id;
    }

//    @Override
//    protected void channelRead0(ChannelHandlerContext channelHandlerContext, NettyChantTypePojo nettyChantTypePojo) throws Exception
//    {
//        NettyChantTypeEnum nettyChantTypeEnum = NettyChantTypeEnum.typeGetMsg(nettyChantTypePojo.getType());
//        NettyMsgService nettyMsgService = SpringUtil.getBean(nettyChantTypeEnum.beanName);
//        nettyMsgService.execute(channelHandlerContext, nettyChantTypePojo,map);
//    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg)
            throws Exception {
        NettyChantTypePojo nettyChantTypePojo = informationConversion(msg, ctx);

        log.info("接收到客户端发送的消息：{}", nettyChantTypePojo.toString());
            NettyMsgService nettyMsgService = mapServiceMap.get(NettyChantTypeEnum.send.beanName);
            nettyMsgService.execute(ctx, nettyChantTypePojo);

    }

    /**
     * 信息转换
     */
    private NettyChantTypePojo informationConversion(TextWebSocketFrame msg, ChannelHandlerContext ctx) {
        NettyChantTypePojo nettyChantTypePojo = null;
        try {
            String text = msg.text();
            nettyChantTypePojo = JSON.parseObject(text, NettyChantTypePojo.class);
        } catch (Exception e) {
            NettyResponseData.err().msg("发送信息的数据类型有误!").sendErr(ctx.channel());
        }
        return nettyChantTypePojo;
    }

    //客户端创建的时候触发，当客户端连接上服务端之后，就可以获取该channel，然后放到channelGroup中进行统一管理
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端连接，创建的时候触发id：" + ctx.channel().id().asShortText());
        System.out.println("当前连接数：" + map.size());
    }


    //客户端销毁的时候触发，
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端断开，当前被移除的channel的短ID是：" + ctx.channel().id().asShortText());
        closeChannel(ctx.channel());
        reconnect();
    }


    public void closeChannel(Channel channel) {
        if (channel != null && channel.isActive()) {
            channel.close().addListener(future -> {
                if (future.isSuccess()) {
                    System.out.println("Channel closed successfully.");
                } else {
                    System.err.println("Failed to close channel: " + future.cause());
                }
            });
        } else {
            System.out.println("Channel is not active, no need to close.");
        }
    }

    private Channel channel;
    public void reconnect() {
        if (channel != null && channel.isActive()) {
            channel.close().addListener((ChannelFuture future) -> {
                if (future.isSuccess()) {
                    System.out.println("Old channel closed, reconnecting...");
                    initiateConnection();
                } else {
                    System.err.println("Failed to close old channel: " + future.cause());
                }
            });
        } else {
            initiateConnection(); // 如果没有旧的连接，则直接连接
        }
    }

    private void initiateConnection() {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(new NioEventLoopGroup())
                .channel(NioSocketChannel.class)
                .handler(new ChatHandler(mapServiceMap));
        // 添加处理器

        bootstrap.connect("localhost", 8087).addListener((ChannelFuture future) -> {
            if (future.isSuccess()) {
                channel = future.channel(); // 更新到新的 Channel
                System.out.println("Reconnected successfully.");
            } else {
                System.err.println("Reconnect failed: " + future.cause());
            }
        });
    }
}
